#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
#include <pthread.h>

#include "../include/client.h"
#include "../notifyADT/notifyADT.h"
#include "../include/pipesclient.h"
#include "../../common/include/common.h"
#include "../../common/include/commonPI.h"
#include "../../common/include/filesystem.h"
#include "../../common/include/general.h"
#include "../../common/include/menu.h"
#include "../../common/include/split.h"

/* fifos del cliente */
int fdpriv = -1;
char priv[MAX_FIFO_LEN] = {0};
int cliPrivfd = -1;
char cliPriv[MAX_FIFO_LEN] = {0};

/* fifo publico del server */
char *fifo = "/tmp/public";

/* Externs de client.c */
extern int logged;
extern watchD w;
extern char *syncPath;
extern char splitVal;
extern pthread_t threads[SPLITS_QUANTITY];
extern int sons[SPLITS_QUANTITY];
extern int doLS;
extern char lastComm[FILE_LEN];

int
mainPI(void)
{
    /* Handlers de SIGS */
    (void)signal(SIGINT, sighandINTPI);

    readCommandsPI();

    if (close (fdpriv))
        fatal ("fifo close failed\n");

    return 0;
}

void
readCommandsPI(void)
{
    int i;
    int ret = 1;
    char command[MAX_COMMAND_LEN+1] = {0};

    char * commands[] = {"nombre", "lista", "agregar", "remover", "salir", "commit"};

    int cant_comms = sizeof(commands) / sizeof(commands[0]);

    int (*pFunct[]) (void)= {nombrePI, listaPI, agregarPI, removerPI, salirPI, commitPI};

    fprintf (stdout, "\n<>: ");
    getLine (command, MAX_COMMAND_LEN, stdin);

    for (i=0 ; i < cant_comms+1 ; i++)
    {
        if (i == cant_comms)
        {
           fprintf (stdout, "\nError: Invalid command\n<>: ");
           getLine (command, MAX_COMMAND_LEN, stdin);
           i = -1;
        }
        else if (strcmp (command, commands[i]) == 0)
        {
            if(i == QUIT_POS)
            {
                closeAllPI();
                exit(0);
                return;
            }

            if (i == NAME_POS)
            {
                ret = pFunct[i] ();
            }
            else
            {
                if (!logged)
                {
                    fprintf (stdout, "Not logged in.\n");
                }
                else
                {
                    ret = pFunct[i] ();
                }
            }

            /* HACK: Si la funcion devuelve -1 salir */
            if (ret == -1)
                exit(0);

            fprintf (stdout, "\n<>: ");
            getLine (command, MAX_COMMAND_LEN, stdin);
            i = -1;
        }
    }

    return;
}

int nombrePI(void)
{
    char name[50] = {0};
    char msg[100] = {0};
    int fd, nwrite, ans, totlen, splitRet, len =0;

    fprintf (stdout, "\nInsert your name: ");
    getLine (name, MAX_COMMAND_LEN, stdin);

    sprintf(priv, "/tmp/fifo%s", name);
    sprintf(cliPriv, "%sP", priv);

    if (mkfifo (priv, 0666) == -1)
    {
        if (errno != EEXIST)
            fatal ("receiver: mkfifo\n");
    }

    if ((fdpriv = open (priv, O_RDWR)) < 0)
    {
        fatal ("fifo open failed\n");
        return -1;
    }

    if (mkfifo (cliPriv, 0666) == -1)
    {
        if (errno != EEXIST)
            fatal ("receiver: mkfifo\n");
    }

    if ((cliPrivfd = open(cliPriv, O_RDWR)) < 0)
        fatal ("fifo open failed\n");

    if ((fd = open(fifo, O_WRONLY | O_NONBLOCK)) < 0)
        return fatal(   "ERROR: Can't open server's public fifo.\n"
                        "SOLUTION: Check server's status.\n");

    len = strlen(priv);
    len += strlen(name);
    len += 1; /* Por la coma */

    sprintf(msg, "%d,2,%d,%s,%s", logged, len, priv, name);
    totlen = strlen (msg);

    if ((nwrite = writeWithTimeout(fd, msg, totlen, TIMEOUT)) == -1)
        fatal("Message write failed\n");

    if (close (fd))
        fatal ("Fifo close failed\n");

    ans = rcvFifoAns(priv);

    if (ans != COM_ACK)
        return fatal("ERROR: Can't connect to the server.\n"
                     "SOLUTION: You are already connected or max clients reached.\n");

    logged = readcomID(priv);

    /*Se splitea dependiendo de los parámetros.*/
    if (splitVal == 't')
        splitRet = split(listenSrvPI, NULL, (void *)&threads[LISTSRV_SPLIT],
                    splitVal, endCiclesPI);
    else
        splitRet = split(listenSrvPI, NULL, (void *)&sons[LISTSRV_SPLIT],
                    splitVal, endCiclesPI);

    if ( splitRet != 1)
        fatal(  "ERROR: Split failed.\n"
                "SOLUTION: Check SPLITS_QUANTITY.\n");

    return 1;
}

int listaPI(void)
{
    char msg[100] = {0};
    int fd, nwrite;
    int len, totlen;

    len = strlen (priv);

    sprintf(msg, "%d,%d,%d,%s", logged, COM_LIST, len, priv);
    totlen = strlen (msg);

    if ((fd = open(fifo, O_WRONLY | O_NONBLOCK)) < 0)
    {
        fatal(  "ERROR: Can't open server's public fifo.\n"
                "SOLUTION: Check server's status.\n");
    }

    if ((nwrite = writeWithTimeout(fd, msg, totlen, TIMEOUT)) == -1)
    {
        fatal(  "ERROR: Timeout while writting server's public fifo.\n"
                "SOLUTION: Check server's status.\n");
    }

    if (close (fd))
    {
        fatal(  "ERROR: Can't close server's public fifo.\n"
                "SOLUTION: Check server's status.\n");
    }

    return 1;
}

void atenderListaPI(void)
{
    int size, comm;
    char msgbuf[MSGSIZE+1] = {0};
    char fifo_serv[50] = {0};
    int name_len;
    char dir[50] = {0};
    int cliPrivSize = 0;
    char resp[MSGSIZE+1] = {0};
    int fdserv;
    int index = 1;

    cliPrivSize = strlen(cliPriv);

    size = readsize (fdpriv);

    if (readWithTimeout(fdpriv, msgbuf, size, TIMEOUT) < 0)
        fatal ("Msg read failed\n");

    strcpy (fifo_serv, msgbuf);

    sprintf(resp, "%d,%d,%s", COM_ACK, cliPrivSize, cliPriv);
    cliPrivSize = strlen(resp);

    if ((fdserv = open(fifo_serv, O_WRONLY)) < 0)
        fatal ("fifo open failed\n");


    send_data_fifo(fdserv, resp, cliPrivSize);
    comm = readcom (cliPrivfd);

    while (comm != COM_END)
    {
        name_len = readsize(cliPrivfd);

        if (readWithTimeout(cliPrivfd, dir, name_len, TIMEOUT) < 0)
            fatal ("Msg read failed\n");

        printf("%2d %s\n", index++, dir);

        while (name_len)
        {
            dir[--name_len] = 0;
        }

        sndFifoAns(fifo_serv, COM_ACK);
        comm = readcom(cliPrivfd);
    }

    if (close (fdserv))
        fatal ("fifo close failed\n");
    return;
}

int agregarPI(void)
{
    char msg[100] = {0};
    int fd, nwrite, len, totlen;
    char dir[50] = {0};

    fprintf (stdout, "\nInsert a Dir: ");
    getLine (dir, MAX_COMMAND_LEN, stdin);

    len = strlen(priv);
    len += strlen(dir);
    len += 1; /* Por la coma */

    sprintf(msg, "%d,4,%d,%s,%s", logged, len, priv, dir);
    totlen = strlen (msg);

    if ((fd = open(fifo, O_WRONLY)) < 0)
        fatal ("fifo open failed\n");

    if ((nwrite = send_data_fifo(fd, msg, totlen)) < 0)
        fatal("message write failed\n");

    if (close (fd))
        fatal ("fifo close failed\n");

    return 1;
}

void atenderAddPI(void)
{
    int size;
    char fifo_serv[50] = {0};
    char msgbuf[100] = {0};
    char currPath[FILE_LEN];
    char dir[50] = {0};
    int comm, path_size, nread;
    char path[100] = {0};
    char buffer[BUF_SIZE] = {0};
    FILE * pfile;
    int cliPrivSize = strlen(cliPriv);
    char resp[MSGSIZE +1] = {0};
    int fdserv;

    size = readsize(fdpriv);

    size -= readFifo(fifo_serv);

    if (readWithTimeout(fdpriv, dir, size, TIMEOUT) < 0)
        fatal ("msg read failed\n");

    sprintf(currPath,"%s/%s",syncPath, dir);
    if (!startFolder(currPath))
    {
        fatal ("Couldn't startFolder.\n");
    }

    sprintf(resp, "%d,%d,%s", COM_ACK, cliPrivSize, cliPriv);
    cliPrivSize = strlen(resp);

    if ((fdserv = open(fifo_serv, O_WRONLY)) < 0)
        fatal ("fifo open failed\n");


    send_data_fifo(fdserv, resp, cliPrivSize);

    comm = readcom(cliPrivfd);

    while (comm != COM_END)
    {
        path_size = readsize(cliPrivfd);

        if (readWithTimeout(cliPrivfd, msgbuf, path_size, TIMEOUT) < 0)
            fatal ("msg read failed\n");

        msgbuf[path_size] = 0;
        sscanf (msgbuf, "%d,%s", &size, path);


        /*it's a dir*/
        if (size == -1)
        {
            mkdir(path, 0744);
            sndFifoAns(fifo_serv, COM_ACK);
        }
        else
        {
            if((pfile = fopen(path, "w")) == NULL)
                fatal ("Error creating file\n");

            nread = 0;
            sndFifoAns(fifo_serv, COM_ACK);
            while (size > 0)
            {
                if (size >= BUF_SIZE)
                    nread = BUF_SIZE;
                else
                    nread = size;

                if (readWithTimeout(cliPrivfd, buffer, nread, TIMEOUT) < 0)
                    {
                        sndFifoAns(fifo_serv, COM_ERR);
                        fatal("msg read failed\n");
                    }

                    if ((fwrite(buffer, 1, nread, pfile)) < nread)
                    {
                        sndFifoAns(fifo_serv, COM_ERR);
                        fatal("File write failed\n");
                    }

                    sndFifoAns(fifo_serv, COM_ACK);

                    size -= nread;

            }
                if ((fclose (pfile)) == EOF)
                    fatal("file close failed\n");
        }

        comm = readcom(cliPrivfd);
    }

    if(setWatchs(currPath, &w) == -1)
    {
        fprintf(stderr, "Error en setWatchs\n");
        return ;
    }

    printf("%s added successfully\n", dir);
    close(fdserv);
    return;
}

int removerPI(void)
{
    int len, nwrite, fd, totlen;
    char msg [MSGSIZE] = {0};
    char dir[MAX_DIR_LEN] = {0};

    fprintf (stdout, "\nInsert a Sync Dir: ");
    getLine (dir, MAX_DIR_LEN, stdin);

    if (isDir(dir) != 1)
    {
        printf("%s is not a dir\n", dir);
        return 1;
    }

    len = strlen (priv);
    len += strlen (dir);
    len += 1;

    sprintf(msg, "%d,%d,%d,%s,%s", logged, COM_REMOVE, len, priv, dir);
    totlen = strlen (msg);

    if ((fd = open(fifo, O_WRONLY)) < 0)
        fatal ("fifo open failed\n");

    if ((nwrite = writeWithTimeout(fd, msg, totlen, TIMEOUT)) == -1)
        fatal("message write failed\n");

    if (close (fd) < 0)
        fatal ("fifo close failed\n");

    return 1;

}

void atenderRemovePI(void)
{
    int size;
    char dir[MAX_DIR_LEN] = {0};
    char w_dir[MAX_DIR_LEN] = {0};

    size = readsize(fdpriv);

    if (readWithTimeout(fdpriv, dir, size, TIMEOUT) < 0)
        fatal ("msg read failed\n");

    sprintf(w_dir,"./%s", dir);
    if ((remWatch(&w, w_dir)) == -1)
        fatal ("Couldn't remove watch of dir\n");

    return ;
}

int salirPI(void)
{
    int len, nwrite, fd, totlen;
    char msg [MSGSIZE];

    if (logged)
    {
        len = strlen (priv);

        sprintf(msg, "%d,%d,%d,%s", logged, COM_CLOSE, len, priv);
        totlen = strlen (msg);

        if ((fd = open(fifo, O_WRONLY | O_NONBLOCK )) < 0)
            return fatal(   "ERROR: Can't open server's public fifo.\n"
                            "SOLUTION: Check server's status.\n");


        if ((nwrite = writeWithTimeout(fd, msg, totlen, TIMEOUT)) == -1)
            return fatal(   "ERROR: Can't write server's public fifo.\n"
                            "SOLUTION: Check server's status.\n");


        if (close (fd) < 0)
            return fatal(   "ERROR: Can't close server's public fifo.\n"
                            "SOLUTION: Check server's status.\n");

    }

    return 1;

}

int commit_filePI(int fdpriv, char * priv, char * path, int type)
{
    int len, totlen;
    char msg[MSGSIZE] = {0};
    char aux_msg[MSGSIZE] = {0};
    int fd, nwrite;
    char dir_path[FILE_LEN] = {0};
    int flag = 0, i;

    len = strlen (path);

    for (i = 0; i < len && flag < 2; i++)
    {
        dir_path[i] = path[i];

        if (path[i] == '/')
        {
            flag++;
        }
    }

    sprintf(aux_msg, "%s,%s,%d", priv, path, type);


    len = strlen(aux_msg);

    if (!canCommit (dir_path))
    {
        fatal("Conflicts, can't commit\n");
        return 0;
    }

    sprintf(msg, "%d,%d,%d,%s", logged, COM_COMMIT, len, aux_msg);
    totlen = strlen (msg);

    if ((fd = open(fifo, O_WRONLY)) < 0)
            fatal ("fifo open failed\n");

    if ((nwrite = send_data_fifo(fd, msg, totlen)) < 0)
        fatal("message write failed\n");

    if (close (fd))
        fatal ("fifo close failed\n");

    return 1;
}

void atenderCommitPI(void)
{
    int size;
    char fifo_serv[MSGSIZE] = {0};
    char path[FILE_LEN] = {0};
    int back;
    char privAns[MSGSIZE+1] = {0};
    int cliPrivSize = strlen(cliPriv);
    int fdserv;


    size = readsize(fdpriv);
    size -= readFifo(fifo_serv);

    if (readWithTimeout(fdpriv, path, size, TIMEOUT) < 0)
        fatal ("msg read failed\n");

    if ((fdserv = open(fifo_serv, O_WRONLY )) < 0)
        fatal ("fifo open failed\n");

    sprintf(privAns, "%d,%d,%s", SND_PRIV, cliPrivSize, cliPriv);
    size = strlen(privAns);
    send_data_fifo(fdserv, privAns, size);

    if ((back = rcvFifoAns(cliPriv)) != COM_ACK)
    {
        printf("%s not commited, error received\n", path);
        return;
    }

    if (snd_file_fifo (fifo_serv, cliPriv, path, 0) < 0)
    {
        printf("%s not commited\n", path);
        return;
    }

    if ((back = rcvFifoAns(cliPriv)) != COM_ACK)
    {
        printf("%s not commited, error received\n", path);
        return;
    }
    close(fdserv);

    return ;
}

int commitPI(void)
{
    char aux_path[FILE_LEN] = {0};
    int resp;
    int type = 0;
    char chtype[MAX_COMMAND_LEN] = {0};
    char  * path;

    fprintf (stdout, "\nInsert a Path: ");
    getLine (aux_path, FILE_LEN, stdin);

    path = strdup(aux_path);

    fprintf (stdout, "\nAdd (1) or Delete(0): ");
    getLine (chtype, MAX_COMMAND_LEN, stdin);

    sscanf(chtype, "%d", &type);

    resp = commit_filePI(fdpriv, priv, path, type);

    if (resp == 1)
        printf("%s commited OK\n", path);
    else
        printf("%s commited ERROR\n", path);

    return 1;
}

void *
listenSrvPI(void *parmsLS)
{
    fd_set master_set, working_set;
    char ch;
    struct timeval tw, tm;

    tm.tv_sec  = SEC_TIMEOUT;
    tm.tv_usec = 0;
    FD_ZERO(&master_set);

    /*Inicializo w*/
    w.waList = NULL;
    if ((w.fd = notify()) == -1)
    {
        fprintf(stderr, "Error when calling notify()\n");
        return NULL;
    }
    FD_SET(w.fd, &master_set);
    FD_SET(fdpriv, &master_set);


    while(doLS)
    {
        memcpy(&working_set, &master_set, sizeof(master_set));
        memcpy(&tw, &tm, sizeof(struct timeval));

        if( select(w.fd + 1, &working_set, (fd_set *)0, (fd_set *)0, &tw) < 0)
        {
            if (errno == EINTR)
                continue;
            else
                fatal ("select failed\n");
        }

        if (FD_ISSET (0, &working_set))
        {
            read(0, &ch, 1);
            printf("%c\n", ch);
        }

        if (FD_ISSET (fdpriv, &working_set))
        {
            takeSrvPI();
        }

        if (FD_ISSET (w.fd, &working_set))
        {
            makeCommitPI();
        }
    }

    return NULL;
}

int takeSrvPI(void)
{

    switch (readcom(fdpriv))
    {
        case COM_SND_DIRLIST:
            atenderListaPI();
            break;

        case COM_SND_FILES:
            printf("Add in progress!\n");
            atenderAddPI();
            break;

        case COM_RCV_COMMIT:
            printf("Commit in progress!\n");
            atenderCommitPI();
            break;

        case WILL_UPDATE:
            printf("Will update!\n");
            atenderWillUpdatePI();
            return 0;
            break;

        case COM_SND_COMMIT:
            printf("Update in progress!\n");
            atenderUpdatePI();
            break;

        case COM_RMV_OK:
            printf("Remove ok!\n");
            atenderRemovePI();
            break;

        case COMMIT_OK:
            printf("Commit (del) ok!\n");
            break;

        case DIR_ERR:
            printf("Invalid dir!\n");
            break;

        case IS_SYNC:
            printf("Dir already syncronized\n");
            break;

        case IS_BUSY:
            printf("Performing another action, please try later\n");
            return -1;
            break;

        case COM_ERR:
            printf("Error occurred\n");
            break;

        default :
            printf("Command not understood\n");
    }

    return 1;
}

int makeCommitPI(void)
{
    int i = 0, len, flag, resp;
    char buf[BUF_LEN_NOTIF] = {0};
    char * path = NULL;
    struct inotify_event *event;
    char completePath[FILE_LEN] = {0};

    len = read(w.fd, buf, BUF_LEN_NOTIF);
    if(len == -1)
    {
        fprintf(stderr, "Error en read\n");
        return 0;
    }

    i = 0;

    while (i < len)
    {
        flag = 0;

        event = (struct inotify_event *) &buf[i];
        if (event->len == 0)
        {
            i += EVENT_SIZE + event->len;
            continue;
        }

        if ((path = getWatchCompletePath(event, &w)) == NULL)
        {
            i += EVENT_SIZE + event->len;
            continue;
        }

        sprintf(completePath, "%s/%s", path, event->name);

        free(path);
        path = NULL;

        if( (strcmp(fileExt(event->name), ".new") != 0) &&
            (strcmp(fileExt(event->name), ".old") != 0) &&
            (strcmp(fileExt(event->name), ".mine") != 0) )
        {
            if(strcmp(completePath, lastComm) != 0)
            {
                switch(event->mask)
                {
                    case MOVE_TO_MASK:
                    case ADD_DIR:
                    case ADD_MASK:
                        do{
                            resp = commit_filePI(fdpriv, priv, completePath, 1);
                            if (resp)
                                flag = takeSrvPI();
                         }while(flag == -1);
                        break;

                    case MOD_MASK:
                        do{
                            resp = commit_filePI(fdpriv, priv, completePath, 1);
                            if (resp)
                                flag = takeSrvPI();
                        }while( flag == -1);
                        break;

                    case DEL_DIR:
                        do{
                            resp = commit_filePI(fdpriv, priv, completePath, 2);
                            if (resp)
                                flag = takeSrvPI();
                        }while(flag == -1);
                        i += EVENT_SIZE + event->len;
                        continue;
                        break;

                    case MOVE_FROM_MASK:
                    case DEL_MASK:
                        do{
                            resp = commit_filePI(fdpriv, priv, completePath, 0);
                            if (resp)
                                flag = takeSrvPI();
                        }while(flag == -1);
                        break;


                    default:
                        printf("Error en makeCommit con mask = %u\n", event->mask);
                        break;
                }
            }
            else
                clrtext(lastComm, FILE_LEN);
        }
        else
        {
            int k = strlen(completePath) - 1;
            sprintf(lastComm, "%s", completePath);
            while(lastComm[k] != '.' && k)
                k--;
            if (k)
                lastComm[k] = 0;
        }
        if(event->mask != DEL_DIR)
        {
            if(update(&w, event) == -1)
            {
                fprintf(stderr, "Error en upgrade\n");
            }
        }
        i += EVENT_SIZE + event->len;

    }

    return 1;
}

void atenderUpdatePI(void)
{
    int size;
    char fifo_serv[50] = {0};
    char msgbuf[100] = {0};
    char currPath[FILE_LEN];
    char dir[50] = {0};
    int comm, path_size, nread, type = 5;
    char path[100] = {0};
    char buffer[BUF_SIZE] = {0};
    FILE * pfile;
    char c;
    int cliPrivSize = strlen(cliPriv);
    char resp[MSGSIZE+1] = {0};
    int fdserv = 0;
    char newpath[100] = {0};


    size = readsize(fdpriv);

    size -= readFifo(fifo_serv);

    size -= readFifo(dir);

    if (readWithTimeout(fdpriv, &c, 1, TIMEOUT) < 0)
        fatal ("msg read failed\n");

    sscanf(&c, "%d", &type);

    sprintf(currPath,"%s/%s",syncPath, dir);

    sprintf(resp, "%d,%d,%s", COM_ACK, cliPrivSize, cliPriv);
    cliPrivSize = strlen(resp);

    if ((fdserv = open(fifo_serv, O_WRONLY)) < 0)
        fatal ("fifo open failed\n");


    send_data_fifo(fdserv, resp, cliPrivSize);

    if (type == ADD_MOD)
    {
        comm = readcom(cliPrivfd);

        path_size = readsize (cliPrivfd);

        if (readWithTimeout(cliPrivfd, msgbuf, path_size, TIMEOUT) < 0)
            fatal ("msg read failed\n");

        msgbuf[path_size] = 0;
        sscanf (msgbuf, "%d,%s", &size, path);
        sprintf(newpath, "%s.new", path);

        /*it's a dir*/
        if (size == -1)
        {
            /* TODO: mandar COM_ERR y recibirlo en el serv */
            if (mkdir(path, 0744) == -1)
            {
                printf("ERROR: creating dir: %s\n", path);
                return ;
            }
            sprintf(lastComm, "%s", path);

            sndFifoAns(fifo_serv, COM_ACK);
        }
        else
        {
            if((pfile = fopen(newpath, "w")) == NULL)
                fatal ("Error creating file\n");

            nread = 0;
            sndFifoAns(fifo_serv, COM_ACK);
            while (size > 0)
            {
                if (size >= BUF_SIZE)
                    nread = BUF_SIZE;
                else
                    nread = size;

                if (readWithTimeout(cliPrivfd, buffer, nread, TIMEOUT) < 0)
                {
                    sndFifoAns(fifo_serv, COM_ERR);
                    fatal("msg read failed\n");
                }

                if ((fwrite(buffer, 1, nread, pfile)) < nread)
                {
                    sndFifoAns(fifo_serv, COM_ERR);
                    fatal("File write failed\n");
                }

                sndFifoAns(fifo_serv, COM_ACK);

                size -= nread;

            }

            if ((fclose (pfile)) == EOF)
                fatal("file close failed\n");

            if (rename(newpath, path) != 0)
            {
                    printf("Error renaming %s\n", newpath);
                    return;
            }
        }
    }
    else if(type == DEL_COMMIT)
    {
        if (remove(dir) != 0)
        {
                //sndFifoAns(fifo_serv, COM_ERR);
        }
        else
                //sndFifoAns(fifo_serv, COM_ACK);
            sprintf(lastComm, "%s", dir);
    }
    else if(type == DEL_DIR_COMMIT)
    {

        if (rmdir(dir) != 0)
        {
                //sndFifoAns(fifo_serv, COM_ERR);
        }
        else
                //sndFifoAns(fifo_serv, COM_ACK);
            sprintf(lastComm, "%s", dir);
    }

    close(fdserv);
    return;
}

void atenderWillUpdatePI(void)
{
    int size;
    char  minePath[FILE_LEN] = {0};
    char dir[FILE_LEN] = {0};

    size = readsize(fdpriv);

    if (readWithTimeout(fdpriv, dir, size, TIMEOUT) < 0)
        fatal ("msg read failed\n");

    sprintf(minePath, "%s.mine", dir);

    cp(dir, minePath);
    fatal("Conflicts occured, fix before commiting\n");


    return;
}

void
closeAllPI(void)
{
    int i, stat;

    doLS = 0;

    if (logged)
    {
        salirPI();
        if (splitVal == 't')
        {
            for( i = 0 ; i < SPLITS_QUANTITY ; i++)
            {
                pthread_join(threads[i], NULL);
            }
        }
        else
        {
            for( i = 0 ; i < SPLITS_QUANTITY ; i++)
            {
                kill(sons[i], SIGUSR1);
                waitpid (sons[i], &stat, 0);
            }
        }

        rm(priv);
        rm(cliPriv);
    }

    exit(0);
    return;
}

void sighandINTPI(int signo)
{
    printf("\nSIGINT catched\n");
    closeAllPI();
}

void endCiclesPI(int signo)
{
    doLS = 0;

    return;
}

int readFifo(char * fifo_serv)
{
    int i = 0;

    do
    {
        readWithTimeout(fdpriv, &(fifo_serv[i]), 1, TIMEOUT);

    }while (fifo_serv[i++] != ',');

    fifo_serv[i-1] = 0;

    return i;
}
